#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <string.h>
#include <time.h>

typedef struct NODE {
    int data;
    struct NODE* next;
}Node;

Node* head = NULL;

// 定义互斥锁
pthread_mutex_t mutex;

// 定义条件变量
pthread_cond_t cond;

// 生产者线程
void* producer(void* arg) {
    Node* pCur = NULL;

    while(1) {
        // 生产一个结点
        pCur = (Node*)malloc(sizeof(Node));
        if(NULL == pCur) {
            perror("malloc err: ");
            exit(1);
        }
        
        pCur->data = rand() % 10000;
        printf("pCur: [%d]\n", pCur->data);   // 标记结点生产成功
        
        // 上线商品 --> 把结点加入到链表中
        // 此时需要操作共享资源
        pthread_mutex_lock(&mutex);
        pCur->next = head;
        head = pCur;
        pthread_mutex_unlock(&mutex);
        
        // 通知消费消费 --> 唤醒消费者线程  
        pthread_cond_signal(&cond);
        sleep(rand() % 3);
    }

}

// 消费者线程
void* consumer(void* arg) {
    Node* pCur = NULL;

    while(1) {
        pthread_mutex_lock(&mutex);

        if(NULL == head) {
            // 条件不满足，消费者需要阻塞等待
            // 条件不满足的时候，消费者阻塞等待，等待生产着解锁
            // 如果条件满足(在生产者线程中，被 pthread_cond_signal 函数通知),解锁阻塞，并尝试加锁
            pthread_cond_wait(&cond, &mutex);
        }
        
        printf("C: [%d]\n", head->data);
        pCur = head;
        head = head->next;
        
        pthread_mutex_unlock(&mutex);

        if(pCur != NULL) {
            free(pCur);
            pCur = NULL;
        }
        
        sleep(rand() % 3);
    }


}


int main()
{
    srand((unsigned int)time(NULL));

    int ret;
    pthread_t trd1;
    pthread_t trd2;

    // 初始化互斥锁和条件变量
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);

    // 让生产者生产结点
    ret = pthread_create(&trd1, NULL, producer, NULL);
    if(ret != 0) {
        printf("pthread_creat error: %s\n", strerror(ret));
        return -1;
    }

    // 让消费着消费结点
    ret = pthread_create(&trd2, NULL, consumer, NULL);
    if(ret != 0) {
        printf("pthread_creat error: %s\n", strerror(ret));
        return -1;
    }
    

    pthread_join(trd1, NULL);
    pthread_join(trd2, NULL);
    
    // 释放互斥锁
    pthread_mutex_destroy(&mutex);
    
    // 释放条件变量
    pthread_cond_destroy(&cond);

    return 0;
}

